package ar.fi.uba.celdas.ambiente.modelo;

import ar.fi.uba.celdas.interfaces.ambiente.IAccion;
import ar.fi.uba.celdas.interfaces.ambiente.IInfoRobot;
import ar.fi.uba.celdas.interfaces.bc.IBaseConocimientos;
import ar.fi.uba.celdas.interfaces.bc.Regla;
import ar.fi.uba.celdas.interfaces.bc.Sensor;
import ar.fi.uba.celdas.interfaces.planificacion.IPlanificacion;
import ar.fi.uba.celdas.interfaces.ponderador.IPonderador;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;

public class MockBaseConocimientos implements IBaseConocimientos {

	Random random = new Random(0);
	ArrayList<Regla> reglas = new ArrayList<Regla>();
	IInfoRobot robot = null;
	
	public MockBaseConocimientos() {
	}

	@Override
	public List<Regla> getReglas() {
		if (robot != null && reglas.size() < 1000 && random.nextFloat() < .1f){
			Regla r = new Regla();
			for (Sensor s : robot.getEstado()){
				if (random.nextBoolean())
					r.getCondiciones().add(s.clone());
				else if (random.nextBoolean())
					r.getCondicionesNegadas().add(s.clone());
			}
			
			r.getPredicciones().addAll(robot.getEstado());
			
			if (random.nextBoolean()){
				r.getAcciones().add(accion(robot, Robot.NOMBRE_ACCION_ROTAR90));
			} else if (random.nextBoolean()){
				r.getAcciones().add(accion(robot, Robot.NOMBRE_ACCION_ROTAR270));
			}
			r.getAcciones().add(accion(robot, Robot.NOMBRE_ACCION_AVANZAR));
			r.setExitos(Math.abs(random.nextInt()) % 1000);
			r.setUso(Math.abs(random.nextInt()) % 1000);
			r.setUtilidad(Math.abs(random.nextInt()) % 1000);
			reglas.add(r);
		}
		return reglas;
	}

	@Override
	public Collection<Sensor> getObjetivo() {
		return new ArrayList<Sensor>();
	}

	@Override
	public Collection<Sensor> getEstadoAnterior() {
		return new ArrayList<Sensor>();
	}

	@Override
	public Collection<Sensor> getEstadoActual() {
		return new ArrayList<Sensor>();
	}

	@Override
	public Collection<IAccion> getAccionesDisponibles() {
		return new ArrayList<IAccion>();
	}

	@Override
	public List<IAccion> procesarSiguientesAcciones(IInfoRobot infoRobot) {
		this.robot = infoRobot;
		ArrayList<IAccion> acciones = new ArrayList<IAccion>();
		if (sePuedeAvanzar(infoRobot)){
			acciones.add(accion(infoRobot,Robot.NOMBRE_ACCION_AVANZAR));			
		} else{
			if (random.nextBoolean())
				acciones.add(accion(infoRobot,Robot.NOMBRE_ACCION_ROTAR90));
			else
				acciones.add(accion(infoRobot,Robot.NOMBRE_ACCION_ROTAR270));
			acciones.add(accion(infoRobot,Robot.NOMBRE_ACCION_AVANZAR));
		}		
		return acciones;
	}


	private IAccion accion(IInfoRobot infoRobot, String nombreAccion) {
		for (IAccion accion : infoRobot.getAccionesDisponibles())
			if (accion.getNombre().equals(nombreAccion))
				return accion;
		throw new RuntimeException("No existe la acción de nombre " + nombreAccion);
	}

	private boolean sePuedeAvanzar(IInfoRobot infoRobot) {
		for (Sensor sensor : infoRobot.getEstado()){
			if (sensor.getNombre().equals(Robot.NOMBRE_SENSOR_DIST_ADELANTE))
				return sensor.getValor() > 0;
		}
		throw new RuntimeException("No existe el sensor de nombre " + Robot.NOMBRE_SENSOR_DIST_ADELANTE);
	}

	@Override
	public int getMaxValor(Sensor sensor) {
		return 0;
	}

	@Override
	public int getMinValor(Sensor sensor) {
		return 0;
	}
	
	@Override
	public void setPlanificador(IPlanificacion planificador) {
	}

	@Override
	public void setPonderador(IPonderador ponderador) {
	}

	@Override
	public Collection<Sensor> getEstadosConocidos() {
		return new ArrayList<Sensor>();
	}
	
}
